
var express = require('express');
var router = express.Router();
const {Category,Course} = require('../../models')
const {Op} = require('sequelize')
console.log(Category);
const {NotFoundError,success,failure} = require('../../utils/response')


/* GET home page. */
router.get('/', async function(req, res, next) {
    try {
        const query = req.query
        // 防止页码不是数字或不是正数或用户没有输入
        const currentPage = Math.abs(Number(query.currentPage)) || 1
        const pageSize = Math.abs(Number(query.pageSize)) || 10
        const offset = (currentPage-1)*pageSize
        const condition = {//定义一个查询条件，这里是按照id字段查找并倒序排序 使用时放在查询语句中即可
            order:[['rank','ASC'],['id','ASC']],
            //实现数据分页时，数据库语句需要下面这两个参数
            limit:pageSize,//此参数为查询几条数据
            offset:offset,//此参数为从第几条数据开始查询
        }

        // 实现模糊查询
        if(query.name){
            condition.where = {
                name:{
                    // Op模块使用前先导入
                    [Op.like]: `%${query.name}%`//此条语句查找条件为包含query.name的数据，百分号代表任意数量任意字符
                }
            }
        }


        // 实现数据分页
        // 此方法返回的count为查询出来的数据总数，rows是最终查询出来的数据
        const {count,rows} = await Category.findAndCountAll(condition) //查询categories表中的所有数据，是异步操作
        res.json({
            status:true,
            message:'查询分类列表成功',
            data:{
                categories:rows,
                pagination:{
                    total:count,
                    currentPage,
                    pageSize,
                }
            }
        });
    } catch (error) {
        failure(res,error)
    }
    
});


// 根据id查找分类
router.get('/:id', async function(req, res, next) {
    try {
        const {id} = req.params
                            //findByPk是根据主键查询(primary key)
        const category = await getCategory(req) //查询categories表中的所有数据，是异步操作
        success(res,'查询分类列表成功',category)
    } catch (error) {
        failure(res,error)
    }
    
});


// 新增分类
router.post('/',async function(req,res){
    try {
        // 白名单过滤 只将req.body中用户传入的参数的某一些写入数据库,
        // 而不是将整个req.body都写入，防止用户对数据库非法操作
        // 在此项目中，id字段由数据库自行自增，不需要人为写入，但不使用白名单过滤的话就可以通过如apifox工具将id自行写入，这样会导致id自增有误
        const body = filterBody(req)
        const category = await Category.create(body)
        // 状态码201代表请求成功并创建了新资源
        success(res,'创建分类成功',{category},201)
    } catch (error) {
        failure(res,error)
    }
    
})



// 删除分类
router.delete('/:id',async function(req,res){
    try {

        // 当我们删除分类后,课程表中可能会出现孤儿记录,即课程表对应的分类表被我们删除了
        // 为了防止出现孤儿记录,有三种方法 
        // 1.设置课程外键约束,删除分类时会报错,但这样会消耗额外性能 
        // 2.删除分类时也删除分类所对应的课程,但这样显然没什么安全性,万一删错了很麻烦
        // 3.删除分类时查询有没有关联的课程,如果有则不删除 这样比较合理

        const count = await Course.count({where:{categoryId:req.params.id}})
        if(count > 0){
            throw new Error('当前分类不为空,无法删除')
        }
        const category = await getCategory(req) 
        await category.destroy()
        success(res,'删除分类成功')
    } catch (error) {
        failure(res,error)
    }
    
})

// 更新分类
router.put('/:id',async function(req,res){
    try {
        const category = await getCategory(req)
        const body = filterBody(req)
        await category.update(body)
        success(res,'更新分类成功',{category})
    } catch (error) {
        failure(res,error)
    }
    
})


function filterBody(req){
    return {
        name:req.body.name,
        rank:req.body.rank
    }
}

// 公共的查询方法，可以将未查询到信息的错误抛出
async function getCategory(req){
    const {id} = req.params
    const category = await Category.findByPk(id)
    if(!category){
        throw new NotFoundError(`ID:${id}的分类未找到`)
    }
    return category
}


module.exports = router;
